﻿using IGeekFan.AspNetCore.Knife4jUI;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Core.SwaggerService
{
    public static class SwaggerExtensions
    {
        /// <summary>
        /// 注入swagger服务
        /// </summary>
        /// <param name="services"></param>
        public static void AddSwaggerService(this IServiceCollection services)
        {
            services.AddMiniProfiler(options => options.RouteBasePath = "/profiler");
            services.AddSwaggerGen(options =>
            {
                OpenApiContact contact = new OpenApiContact()
                {
                    Name = "杨泽",
                    Email = "532050072@qq.com",
                    Url = new Uri("https://gitee.com/tengfei8771")
                };
                // 添加文档信息
                options.SwaggerDoc("base_api", new OpenApiInfo 
                {
                    Title = "基础框架API", 
                    Version = "v1" ,
                    Contact= contact
                });
                options.SwaggerDoc("app_api", new OpenApiInfo { Title = "业务API", Version = "v1",Contact= contact });
                var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
                // 获取xml文件路径
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                options.DocInclusionPredicate((docName, apiDesc) =>
                {
                    if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo))
                    {
                        return false;
                    }
                    else
                    {
                        var version = methodInfo.DeclaringType.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(t => t.GroupName).FirstOrDefault();
                        if (docName.ToLower() == "app_api" && version == null)
                        {
                            return true;
                        }
                        else
                        {
                            return version == docName.ToLower();
                        }

                    }
                });
                // 添加控制器层注释，true表示显示控制器注释
                options.IncludeXmlComments(xmlPath, true);
                options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                {
                    Description = "在下框中输入令牌,格式为:bearer +令牌",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    BearerFormat = "JWT",
                    Scheme = "Bearer"
                });
                options.AddSecurityRequirement(new OpenApiSecurityRequirement
                    {
                        {
                            new OpenApiSecurityScheme{
                                Reference = new OpenApiReference {
                                            Type = ReferenceType.SecurityScheme,
                                            Id = "Bearer"}
                           },new string[] { }
                        }
                    });
            });
        }
        /// <summary>
        /// 使用swagger服务
        /// </summary>
        /// <param name="app"></param>
        public static void UseSwaggerService(this IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (true)//env.IsDevelopment())
            {
                app.UseMiniProfiler();
                app.UseSwagger(c =>
                {
                    c.RouteTemplate = "swagger/{documentName}/swagger.json";
                });
                List<string> groupNames = Assembly.GetEntryAssembly().GetTypes().AsEnumerable()
                    .Where(t => t.GetCustomAttribute<ApiExplorerSettingsAttribute>() != null)
                    .Select(t => t.GetCustomAttribute<ApiExplorerSettingsAttribute>().GroupName).Distinct().ToList();
                app.UseSwaggerUI(c =>
                {
                    c.IndexStream = () =>
                    {
                        return Assembly.GetExecutingAssembly().GetManifestResourceStream($"{Assembly.GetExecutingAssembly().GetName().Name}.SwaggerService.SwaggerIndex.html");

                    };
                    foreach (string groupName in groupNames)
                    {
                        c.SwaggerEndpoint($"/swagger/{groupName}/swagger.json", groupName);
                    }
                });
                app.UseKnife4UI(c =>
                {
                    c.RoutePrefix = string.Empty;
                    foreach (string groupName in groupNames)
                    {
                        c.SwaggerEndpoint($"/swagger/{groupName}/swagger.json", groupName);
                    }
                });
            }
        }
    }
}
